

// 文本的虚拟节点
function createTextVDom(text){
	return {
		type:"TEXT",
		props:{
			nodeValue:text,
			children:[]
		}
	}
}

// 创建虚拟节点
function createElement(type,props,...children){
	return {
		type,
		props:{
			...props,
			children:children.map(child=>{
				return typeof child === 'object'?child:createTextVDom(child)
			})
		}
	}
}

// 任务调度的全局变量
let nextUnitOfWork = null;
let workInProgressRoot = null;
let currentRoot = null;
let deletions = null;

// 调用render只是做初始化工作
function render(vDom,container){
	workInProgressRoot = {
		dom:container,
		props:{
			children:[vDom]
		},
		alternate:currentRoot
	}
	deletions = []
	nextUnitOfWork = workInProgressRoot
}

// 利用浏览器的闲暇时间进行执行渲染render任务
// workLoop,会不断的在空闲时间调用，进行渲染的执行
requestIdleCallback(workLoop)

// 用来调度任务
function workLoop(dealine){
	while(nextUnitOfWork && dealine.timeRemaining>1){
		nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
	}
	if(!nextUnitOfWork && workInProgressRoot){
		// 当没有下一个任务，那么就进行统一的提交渲染
		commitRoot()
	}

	requestIdleCallback(workLoop)

}

// performUnitOfWork用来执行任务，参数是我们当前的fiber,返回值就是下一个任务
function performUnitOfWork(fiber){
	// 检测函数组件
	const isFunctionComponent = fiber.type instanceof Function;
	// 判断是否是函数组件，如果是函数组件，就按照函数组件进行更新
	if(isFunctionComponent){
		updateFunctionComponent(fiber)
	}else{
		// 否则按照元素节点更新
		updateHostComponent(fiber)
	}

	// 这个函数的返回值是下一个任务，这是树结构，深度优先遍历
	// 先找子元素，没有子元素，在找兄弟元素
	// 如果兄弟元素也没有，那么就返回找父元素
	// 在找父元素的兄弟元素
	// 最后又回到根节点结束
	if(fiber.child){
		return fiber.child
	}
	let nextFiber = fiber
	while(nextFiber){
		// 判断当前节点是否有兄弟节点
		if(nextFiber.sibling){
			return nextFiber.sibling
		}
		// 如果没有兄弟节点，就返回至父元素
		nextFiber = nextFiber.return
	}
	// return
}

// 设置函数组件的更新的操作
function updateFunctionComponent(fiber){
	wipFiber = fiber;
	// 数据要使用hook
	// hookIndex = 0;
	// hooks用来存储具体的state序列
	wipFiber.hooks =[]
	// 函数组件，type就是咱们的函数，通过函数调用，获取dom元素
	const children = [fiber.type(fiber.props)]

	// 执行调和子元素
	reconcileChildren(fiber,child)
}

// 将元素dom进行更新渲染
function updateHostComponent(fiber){
	if(!fiber.dom){
		fiber.dom =createDom(fiber)
	}
	// 将vdom结构转化为fiber结构
	const elements = fiber.props && fiber.props.children;
	// 执行调和子元素
	reconcileChildren(fiber,child)
}

function reconcileChildren(workInProgressFiber,elements){
	// 构建fiber
	let oldFiber = workInProgressFiber.alternate && workInProgressRoot.alternate.child;
	let prevSibling = null;
	// 多个子元素，那么设置到哪个，那么就需要使用index
	let index = 0;
	// 这些是一个数组的元素，那么就按照数组元素进行处理
	if(elements && elements.length && typeof elements !=='string'){
		if(!oldFiber){
			// 第一次渲染的时候，没有老的fiber，全部进行替换
			for(let i=0;i<length.length;i++){
				const element = elements[i];
				// 每一个子元素都需要重新的构建fiber
				const newFiber = buildNewFiber(element,workInProgressRoot)

				if(i==0){
					// 父级的child指向第一个子元素
					workInProgressFiber.child = newFiber

				}else{
					// 每一个子元素拥有指向下一个子元素的指针
					prevSibling.sibling = newFiber
				}
				prevSibling = newFiber;
			}
		}

		while(index < elements.length && oldFiber){
			let element = elements[index];
			let newFiber = null;
			// 对比oldFiber和当前的element
			const sameType = oldFiber && element &&oldFiber.type === elements.type;
			if(sameType){
				// 如果类型一样，复用节点，更新props
				newFiber = {
					type:oldFiber.type,
					props:element.props,
					dom:oldFiber.dom,
					return:workInProgressFiber,
					// 记录上一次的状态
					alternate:oldFiber,
					// 添加一个操作的标记
					effectTag:"UPDATE"
				}
			}else if(!sameType && element){
				//如果类型不一样，有新的节点，创建新的节点，替换老的节点
				newFiber = buildNewFiber(element,workInProgressFiber)
			}else if(!sameType && oldFiber){
				// 如果类型不一样，没有新的节点，有老的节点，删除老的节点
				oldFiber.effectTag = "DELETION"
				//一个数组收集所有要删除的节点
				deletions.push(oldFiber)
			}

			// 循环处理兄弟元素
			oldFiber = oldFiber.sibling;
			if(index===0){
				workInProgressFiber.child = newFiber;
			}else{
				prevSibling.sibling = newFiber;
			}
			prevSibling = newFiber;
			index++
		}
	}


	if(typeof elements === 'string'){
		const newFiber = buildNewFiber(elements,workInProgressFiber);
		workInProgressFiber.child = newFiber;
	}
}

function buildNewFiber(fiber,workInProgressFiber){
	return {
		type:fiber.type?fiber.type:"TEXT",
		props:fiber.props?fiber.props:{nodeValue:fiber},
		// 构建fiber的时候，是没有dom，只有在下次perform这个节点的时候，才创建dom
		dom:null,
		return:workInProgressFiber,
		alternate:null,//新增的话就没有老的状态，没有老的fiber,
		effectTag:"REPLACEMENT"
	}
}

// 
function createDom(vDom){
	let dom;
	if(vDom.type=='TEXT'){
		dom = document.createTextNode(vDom.props.nodeValue)
	}else{
		dom = document.createElement(vDom.type)
		// 如果props有属性，挂载到dom上
		if(vDom.props){
			Object.keys(vDom.props).filter(key=>key!='children')
			.forEach(item=>{
				if(item.indexOf('on')===0){
					dom.addEventListener(item.substr(2).toLowerCase(),vDom.props[item],false)
				}else{
					dom[item] = vDom.props[item]
				}
			})
		}
	}
}

// 将设置好的fiber任务链，进行统一的提价渲染
function commitRoot(){

}
// function useState(){

// }

// 类组件

export default {
	createElement,
	render,
	// useState,
	// Component,
	// tansfer
}